require 'depac-common/softlayer'
require 'depac-deployment/environment_configuration'
require 'depac-deployment/update_env'
require 'depac-deployment/helper'
require 'depac-common/constants'
require 'pp'


# This method migrates/configures/re-wires the nodes provisioned.
# Parameters:
#	nodeInfoMap -  The map contains the info of the nodes that need to configured. eg. Appserver, Foundation
#	nodeInfoParamMap - The map contains the info of the nodes to which the newly provisioned nodes(nodeInfoMap) need to be wired. eg. Database node info
#	envConfig - The environment configuration object
def configureInstance(nodeInfoMap, nodeInfoParamMap, envConfig)
  # Get the private key path
  private_key_path = Depac::CloudDeploymentConstants::CLD_DPL_KEYPATH
  
  typeArr = getEnvironmentTypes()
  
  startConfigureTime = Time.new
  
  # build string param for webserver
  stringParamForWebserver = getStringParamForWebServer(nodeInfoParamMap)
 
  typeArr.each do |type|
    # Build a string parameter in role=IP,IP format. eg: database=9.23.45.67
    # This parameter is passed into the migrate/configure script to perform rewiring
    stringParam = getStringParamFromNodeInfoMap(nodeInfoParamMap[type])
    if(nodeInfoMap[type] != nil)
      # Iterate through the nodes in nodeInfoMap to configure/re-wire them to the nodes in nodeInfoParamMap
        ["database", "jms", "appserver", "agent", "intg"].each do |role|
          nodeInfoArr = nodeInfoMap[type][role]
          unless nodeInfoArr then next end
          Depac::Log.write("INFO", "Configuring #{type}:#{role}")
          Depac::Log.write("INFO", Depac::CloudDeploymentConstants::BORDER_LINE)
          
          param = stringParam
          if(role == 'webserver')
                   param = stringParamForWebserver
          end
        
          if (role == 'provisioning' or role == 'wordpress')
            if (envConfig != nil)
              param = "#{param} oms_host_ip=#{envConfig['oms_host_ip']}"
            end
            
            if (envConfig['wordpressdb'] != nil)
              param = "#{param} wordpressdb=#{envConfig['wordpressdb']}"  
            end         
            
            if (envConfig['update_wordpress_host'] != nil)
              param = "#{param} update_wordpress_host=#{envConfig['update_wordpress_host']}"  
            end
            
          end
          if (role == 'appserver' or role == 'agent' or role == 'intg')
            if (envConfig != nil and envConfig['cat_server_ip'] != nil and envConfig['cat_server_hn'] != nil )
              param = "#{param} cat_server_ip=#{envConfig['cat_server_ip']} cat_server_hn=#{envConfig['cat_server_hn']}"              
            end       
          end
          
          if (envConfig != nil and envConfig['newrelicEnablement'] != nil )
              param = "#{param} newrelicEnablement=#{envConfig['newrelicEnablement']}"
          end
          
          if (envConfig != nil and envConfig['logstashServer'] != nil )
              param = "#{param} logstashServer=#{envConfig['logstashServer']}"
          end
          
          if (envConfig != nil and envConfig['newrelicProxyServer'] != nil )
              param = "#{param} newrelicProxyServer=#{envConfig['newrelicProxyServer']}"
          end
          
          if (envConfig != nil and envConfig['commonProxyServer'] != nil )
              param = "#{param} commonProxyServer=#{envConfig['commonProxyServer']}"
          end
          
          if (envConfig != nil and envConfig['smtpServer'] != nil )
              param = "#{param} smtpServer=#{envConfig['smtpServer']}"
          end
          
          if (envConfig != nil and envConfig['LBServer'] != nil )
              param = "#{param} LBServer=#{envConfig['LBServer']}"
          end
          Depac::Log.write("INFO", "the final pramaters for migration is : #{param}")
        
          nodeInfoArr.each do |hostnameIPMap|
		   if (role == 'appserver' or role == 'agent' or role == 'intg')
	            if (envConfig != nil and envConfig['oldDBInfo'] != nil)	
	            	oldhn = envConfig['oldDBInfo']['hostname']
	            	oldip = envConfig['oldDBInfo']['IP']            	            	
		        else
		            oldDBInfo=dbOldHostnameGen(existingEnvConfigObject)	
		            oldhn = oldDBInfo['hostname']
	            	oldip = oldDBInfo['IP']
		        end
	            
	            cmdstr = "ssh -t -t -i #{private_key_path} root@#{hostnameIPMap['IP']} -o StrictHostKeyChecking=no 'echo #{oldip} #{oldhn} >>/etc/hosts'"
		        Depac::Log.write("INFO", "Executing command: " + cmdstr)
		        output =  `#{cmdstr}`
		        Depac::Log.write("INFO", output)
		        Depac::Log.write("INFO", Depac::CloudDeploymentConstants::BORDER_LINE)    
	        end  
		  



            cmdstr = "ssh -t -t -i #{private_key_path} root@#{hostnameIPMap['IP']} -o StrictHostKeyChecking=no 'cd /migration;./#{role}.sh #{param}'"
            Depac::Log.write("INFO", "Executing command: " + cmdstr)
            output =  `#{cmdstr}`
            Depac::Log.write("INFO", output)
            Depac::Log.write("INFO", Depac::CloudDeploymentConstants::BORDER_LINE)
            
                     
          end           
       end           
     end
  end
  endConfigureTime = Time.new
  Depac::Log.write("INFO", "Time taken to configure instances: #{computeDuration(endConfigureTime - startConfigureTime)}")
  Depac::Log.write("INFO", Depac::CloudDeploymentConstants::BORDER_LINE)
end


def getStringParamForWebServer(nodeInfoParamMap)
  finalString = ""
  
  typeArr = getEnvironmentTypes()
  
  typeArr.each do |type|
    if(nodeInfoParamMap[type] != nil and nodeInfoParamMap[type]['appserver'] != nil)
      ips = ""
      nodeInfoParamMap[type]['appserver'].each do |nodeInfo|
        if (ips == "") 
          ips = "#{nodeInfo['IP']}"
        else 
          ips = "#{ips}~#{nodeInfo['IP']}"
        end
      end
    end
    finalString = "#{finalString} #{type}=#{ips}"
  end
  return finalString
end

def getStringParamFromNodeInfoMap(nodeInfoParamMap)
	finalString = ""
	
	if(nodeInfoParamMap != nil)
		nodeInfoParamMap.each do |key, array|
			role = key
			ips = ""
			
			array.each do |hostnameIPMap|
				ip = hostnameIPMap["IP"]
				hostname = hostnameIPMap["hostname"]
				info = hostnameIPMap["info"]
				
				value = ip;
				if (role == "agent" || role == "intg")
					value = "#{info}:#{ip}"
				end
				
				if (ips == "") 
					ips = "#{value}"
				else 
					ips = "#{ips}~#{value}"
				end
			end
			finalString = "#{finalString} #{role}=#{ips}"
		end
	end
	return finalString
end

=begin
nodeInfoMap = Hash.new

dbhostnameIPArr = Array.new
hostnameIPMap1 = Hash.new
hostnameIPMap1['IP'] = "123"
hostnameIPMap1['hostname'] = "dinup"
dbhostnameIPArr.push(hostnameIPMap1)

agenthostnameIPArr = Array.new
hostnameIPMap0 = Hash.new
hostnameIPMap0['IP'] = "123"
hostnameIPMap0['hostname'] = "dinup"
hostnameIPMap0['info'] = "import,search"
agenthostnameIPArr.push(hostnameIPMap0)

hostnameIPMap2 = Hash.new
hostnameIPMap2['IP'] = "5678"
hostnameIPMap2['hostname'] = "dinup123"
dbhostnameIPArr.push(hostnameIPMap2)

apphostnameIPArr = Array.new
hostnameIPMap1 = Hash.new
hostnameIPMap1['IP'] = "123"
hostnameIPMap1['hostname'] = "dinup"
apphostnameIPArr.push(hostnameIPMap1)

hostnameIPMap2 = Hash.new
hostnameIPMap2['IP'] = "5678"
hostnameIPMap2['hostname'] = "dinup123"
apphostnameIPArr.push(hostnameIPMap2)

nodeInfoMap["database"] = dbhostnameIPArr
nodeInfoMap["appserver"] = apphostnameIPArr
nodeInfoMap["agent"] = agenthostnameIPArr

typeInfoMap = Hash.new
typeInfoMap['runtime'] = nodeInfoMap

configureInstance(typeInfoMap, typeInfoMap)
=end
#docker poc
def configureInstanceForDocker(nodeInfoMap, nodeInfoParamMap, envConfig)
  # Get the private key path
  private_key_path = Depac::CloudDeploymentConstants::CLD_DPL_KEYPATH
  
  typeArr = getEnvironmentTypes()
  
  startConfigureTime = Time.new
  
  # build string param for webserver
  stringParamForWebserver = getStringParamForWebServer(nodeInfoParamMap)
 
  typeArr.each do |type|
    # Build a string parameter in role=IP,IP format. eg: database=9.23.45.67
    # This parameter is passed into the migrate/configure script to perform rewiring
    stringParam = getStringParamFromNodeInfoMap(nodeInfoParamMap[type])
    if(nodeInfoMap[type] != nil)
      # Iterate through the nodes in nodeInfoMap to configure/re-wire them to the nodes in nodeInfoParamMap
        ["database", "jms", "appserver", "agent", "intg"].each do |role|
          nodeInfoArr = nodeInfoMap[type][role]
 
          unless nodeInfoArr then next end
          Depac::Log.write("INFO", "Configuring #{type}:#{role}")
          Depac::Log.write("INFO", Depac::CloudDeploymentConstants::BORDER_LINE)
          
          param = stringParam
          if(role == 'webserver')
              param = stringParamForWebserver
          end
        
          if (role == 'appserver' or role == 'agent' or role == 'intg')
            if (envConfig != nil and envConfig['cat_server_ip'] != nil and envConfig['cat_server_hn'] != nil )
               param = "#{param} cat_server_ip=#{envConfig['cat_server_ip']} cat_server_hn=#{envConfig['cat_server_hn']}"              
            end       
          end
          
          #Fix issue:  agent server name not be passed to migration scirpts
          if (role == 'agent')
            if (envConfig != nil and nodeInfoArr !=nil)          
               agentParam="agent"
               nodeInfoArr.each do |node|
                  if agentParam == "agent"
                    agentParam="#{agentParam}=#{node['info']}:#{node['IP']}"
                  else
                    agentParam="#{agentParam}~#{node['info']}:#{node['IP']}"
                  end
               end 
               #param = "#{param} #{agentParam}"   
            end
          end
          
          if (role == 'intg')
            if (envConfig != nil and nodeInfoArr !=nil)          
               intgParam="intg"
               nodeInfoArr.each do |node|
                  if intgParam == "agent"
                    intgParam="#{intgParam}=#{node['info']}:#{node['IP']}"
                  else
                    intgParam="#{intgParam}~#{node['info']}:#{node['IP']}"
                  end
               end 
               #param = "#{param} #{intgParam}"   
            end
          end
          
          if (envConfig != nil and envConfig['newrelicEnablement'] != nil )
              param = "#{param} newrelicEnablement=#{envConfig['newrelicEnablement']}"
          end
          
          if (envConfig != nil and envConfig['logstashServer'] != nil )
              param = "#{param} logstashServer=#{envConfig['logstashServer']}"
          end
          
          if (envConfig != nil and envConfig['newrelicProxyServer'] != nil )
              param = "#{param} newrelicProxyServer=#{envConfig['newrelicProxyServer']}"
          end
          
          if (envConfig != nil and envConfig['commonProxyServer'] != nil )
              param = "#{param} commonProxyServer=#{envConfig['commonProxyServer']}"
          end
          
          if (envConfig != nil and envConfig['smtpServer'] != nil )
              param = "#{param} smtpServer=#{envConfig['smtpServer']}"
          end
          
          if (envConfig != nil and envConfig['LBServer'] != nil )
              param = "#{param} LBServer=#{envConfig['LBServer']}"
          end
          
          Depac::Log.write("INFO", "the final pramaters for migration is : #{param}")
        
          sshPort="22"
	        
        
          nodeInfoArr.each do |hostnameIPMap|
          
             if (role == 'appserver' or role == 'agent' or role == 'intg')
                 if hostnameIPMap['sshPort'] !=nil
                     sshPort=hostnameIPMap['sshPort']
                 end 
             end
         
		     if (role == 'appserver' or role == 'agent' or role == 'intg')
	            if (envConfig != nil and envConfig['oldDBInfo'] != nil)	
	            	     oldhn = envConfig['oldDBInfo']['hostname']
	            	     oldip = envConfig['oldDBInfo']['IP']            	            	
		        else
		                 Depac::Log.write("INFO", "Not find defined oldDBInfo, will generate it based on current db hostname and envName")
                         nodesinfo=envConfig[Depac::CloudDeploymentConstants::RUNTIME_NODES]
                         envName=envConfig[Depac::CloudDeploymentConstants::ENVIRONMENT]

		                 nodesinfo.each do |node|
		                   if node[Depac::CloudDeploymentConstants::ROLE] == "database"
		                       nodeInfo = node[Depac::CloudDeploymentConstants::NODE_INFO] 
                               hostname=nodeInfo[0]['hostname']
		                       oldhn = hostname.split(envName.downcase)[0].upcase+"database.ibm.com"                               
		                       oldip = nodeInfo[0]['IP']	
		                       
		                       envConfig['oldDBInfo']={
                                             'hostname' => oldhn,
                                             'IP' =>oldip
                               }
		                       		                       
		                       #envConfig['oldDBInfo']['hostname']=oldhn
		                       #envConfig['oldDBInfo']['IP']=oldip
		                       Depac::Log.write("INFO", "Generated old db hostname is : #{oldhn}; IP is : #{oldip} ")                
		                      break
		                   end
		                 end 
               end  
                
                param = "#{param} dockerHostIP=#{hostnameIPMap['IP']}" 
	            
	            cmdstr = "ssh -t -t -i #{private_key_path} root@#{hostnameIPMap['IP']} -p #{sshPort} -o StrictHostKeyChecking=no 'echo #{oldip} #{oldhn} >>/etc/hosts'"
		        Depac::Log.write("INFO", "Executing command: " + cmdstr)
		        output =  `#{cmdstr}`
		        Depac::Log.write("INFO", output)
		        Depac::Log.write("INFO", Depac::CloudDeploymentConstants::BORDER_LINE)     
	        end  
  
            cmdstr = "ssh -t -t -i #{private_key_path} root@#{hostnameIPMap['IP']} -p #{sshPort} -o StrictHostKeyChecking=no 'cd /migration;./#{role}.sh #{param}'"
            Depac::Log.write("INFO", "Executing command: " + cmdstr)
            output =  `#{cmdstr}`
            Depac::Log.write("INFO", output)
            Depac::Log.write("INFO", Depac::CloudDeploymentConstants::BORDER_LINE)
                             
          end           
       end           
     end
  end
  endConfigureTime = Time.new
  Depac::Log.write("INFO", "Time taken to configure instances: #{computeDuration(endConfigureTime - startConfigureTime)}")
  Depac::Log.write("INFO", Depac::CloudDeploymentConstants::BORDER_LINE)
end
